#pragma once

enum EDBASE
{
    EDB_CONTACT,
    EDB_CLOG,
    EDB_SCUT,
    EDB_SIM,

    EDB_MAX,
    EDB_NIL = -1
};

class PropertyValues
{
public:
  PropertyValues() : pPropVals(NULL), nPropVals(0)
  {}
  ~PropertyValues()
  { Free(); }

  void Free();

  CEPROPVAL& operator[](int idx)
  { return pPropVals[idx]; }

  CEPROPVAL* pPropVals;
  ULONG      nPropVals;
};

class EdbData
{
public:
  static bool Initialize(HWND hWindow);
  static void Terminate();

  static bool OpenDatabase(EDBASE edb, bool sendNotifications = false);
  static bool OpenDatabase(EDBASE edb, SORTORDERSPECEX* pSortOrder, bool sendNotifications = false);
  static void CloseDatabase(EDBASE edb, bool forcedClose = false);

  static bool FreeNotification(CENOTIFICATION* pNotification);

  static DWORD GetNumRecords(EDBASE edb);

  static CEOID SeekDatabase(EDBASE edb, DWORD dwSeekType, DWORD dwValue, WORD wNumVals = 0, LPDWORD lpdwIndex = NULL);

  static CEOID ReadRecord(EDBASE edb, CEOID oid, PropertyValues& vals, WORD& nPropCount)
  { return ReadRecord(edb, oid, &vals.pPropVals, vals.nPropVals, nPropCount); }
  static CEOID ReadRecord(EDBASE edb, CEOID oid, const CEPROPID* aPropIds, int nPropIds, PropertyValues& vals)
  { return ReadRecord(edb, oid, aPropIds, nPropIds, &vals.pPropVals, vals.nPropVals); }
  static CEOID ReadRecord(EDBASE edb, PropertyValues& vals, WORD& nPropCount)
  { return ReadRecord(edb, &vals.pPropVals, vals.nPropVals, nPropCount); }
  static CEOID ReadRecord(EDBASE edb, const CEPROPID* aPropIds, int nPropIds, PropertyValues& vals)
  { return ReadRecord(edb, aPropIds, nPropIds, &vals.pPropVals, vals.nPropVals); }

  static bool WriteRecord(EDBASE edb, CEOID oid, PropertyValues& vals)
  { return WriteRecord(edb, oid, vals.pPropVals, vals.nPropVals); }
  static bool DeleteRecord(EDBASE edb, CEOID oid);

  static bool IsPropertyEmpty(const CEPROPVAL& prop);
  static bool IsValidString(const CEPROPVAL& prop);
  static bool GetPropertyValue(const CEPROPVAL& prop, TCHAR* buf, size_t maxLen);
  static bool GetPropertyValue(const CEPROPVAL& prop, DWORD& value);
  static bool GetPropertyValue(const CEPROPVAL& prop, LONG& value);
  static bool GetPropertyValue(const CEPROPVAL& prop, INT& value);
  static bool GetPropertyValue(const CEPROPVAL& prop, FILETIME& value);
  static bool GetPropertyDateValue(const CEPROPVAL& prop, TCHAR* buf, size_t maxLen, DWORD dwFlags = DATE_LONGDATE);
  static bool GetPropertyTimeValue(const CEPROPVAL& prop, TCHAR* buf, size_t maxLen, DWORD dwFlags = 0);

private:
  static CEOID ReadRecord(EDBASE edb, CEOID oid, CEPROPVAL** pPropVals, ULONG& nPropVals, WORD& nPropCount);
  static CEOID ReadRecord(EDBASE edb, CEOID oid, const CEPROPID* aPropIds, int nPropIds, CEPROPVAL** pPropVals, ULONG& nPropVals);
  static CEOID ReadRecord(EDBASE edb, CEPROPVAL** pPropVals, ULONG& nPropVals, WORD& nPropCount);
  static CEOID ReadRecord(EDBASE edb, const CEPROPID* aPropIds, int nPropIds, CEPROPVAL** pPropVals, ULONG& nPropVals);
  static bool  WriteRecord(EDBASE edb, CEOID oid, CEPROPVAL* pPropVals, int nPropVals);

private:
  static bool IsOpened(EDBASE edb);
  static bool GetDataDirectory(TCHAR* szBuffer, DWORD dwSize);
  static bool MountDbVol();
  static bool UnmountDbVol();

private:
  static HWND          hWnd;
  static CEGUID        guidVol;
  static bool          isVolMounted;
  static HANDLE        aDbHandlers[EDB_MAX];
  static DWORD         aDbUsers[EDB_MAX];

  static CENOTIFYREQUEST aNotifyReqs[EDB_MAX];
};